package org.example.day03;

import java.math.BigInteger;

/**
 * @author zlxad
 * @version 1.0
 * @description: TODO+
 * 给定一个表达式，求其分数计算结果 <br>  <br> <div>  表达式的限制如下： </div> <div>  <br> </div> <div>  1. 所有的输入数字皆为正整数(包括0) </div> <div>  2. 仅支持四则运算(+ - * /)和括号 </div> <div>  3. 结果为整数或分数, 分数必须化为最简格式(比如6, 3/4, 7/8, 90/7) </div> <div>  4. 除数可能为0，如果遇到这种情况，直接输出&quot;ERROR&quot; </div> <div>  <span>5. 输入和最终计算结果中的数字都不会超出整型范围</span><br> </div> <div>  <span><br> </span> </div> <div>  <span>用例的输入一定合法, 不会出现括号不匹配的情况</span> </div> <div>  <br> </div>
 * <p>
 * 给定一个表达式，求其分数计算结果
 * 表达式的限制如下：
 * <p>
 * 1. 所有的输入数字皆为正整数(包括0)
 * 2. 仅支持四则运算(+ - * /)和括号
 * 3. 结果为整数或分数, 分数必须化为最简格式(比如6, 3/4, 7/8, 90/7)
 * 4. 除数可能为0，如果遇到这种情况，直接输出"ERROR"
 * 5. 输入和最终计算结果中的数字都不会超出整型范围
 * <p>
 * 用例的输入一定合法, 不会出现括号不匹配的情况
 * @date 2024/3/11 15:22
 */
public class test056 {

    private int index = 0;
    private String expression;

    public String calculate(String expr) {
        expression = expr.replaceAll("\\s+", ""); // 移除空格
        index = 0;
        try {
            Fraction result = parseExpression();
            if (result.denominator.equals(BigInteger.ZERO)) {
                return "ERROR";
            }
            return result.simplify().toString();
        } catch (ArithmeticException e) {
            return "ERROR";
        }
    }

    private Fraction parseExpression() {
        Fraction result = parseTerm();
        while (index < expression.length()) {
            char operator = expression.charAt(index);
            if (operator == '+' || operator == '-') {
                index++;
                Fraction next = parseTerm();
                result = operator == '+' ? result.add(next) : result.subtract(next);
            } else {
                break;
            }
        }
        return result;
    }

    private Fraction parseTerm() {
        Fraction result = parseFactor();
        while (index < expression.length()) {
            char operator = expression.charAt(index);
            if (operator == '*' || operator == '/') {
                index++;
                Fraction next = parseFactor();
                result = operator == '*' ? result.multiply(next) : result.divide(next);
            } else {
                break;
            }
        }
        return result;
    }

    private Fraction parseFactor() {
        if (expression.charAt(index) == '(') {
            index++; // 跳过'('
            Fraction result = parseExpression();
            index++; // 跳过')'
            return result;
        } else {
            return parseNumber();
        }
    }

    private Fraction parseNumber() {
        int start = index;
        while (index < expression.length() && Character.isDigit(expression.charAt(index))) {
            index++;
        }
        BigInteger value = new BigInteger(expression.substring(start, index));
        return new Fraction(value, BigInteger.ONE);
    }

    // 分数类，用于处理分数的加减乘除运算和化简
    private static class Fraction {
        BigInteger numerator;   // 分子
        BigInteger denominator; // 分母

        public Fraction(BigInteger numerator, BigInteger denominator) {
            this.numerator = numerator;
            this.denominator = denominator;
        }

        public Fraction add(Fraction other) {
            BigInteger newNumerator = numerator.multiply(other.denominator)
                    .add(denominator.multiply(other.numerator));
            BigInteger newDenominator = denominator.multiply(other.denominator);
            return new Fraction(newNumerator, newDenominator);
        }

        public Fraction subtract(Fraction other) {
            BigInteger newNumerator = numerator.multiply(other.denominator)
                    .subtract(denominator.multiply(other.numerator));
            BigInteger newDenominator = denominator.multiply(other.denominator);
            return new Fraction(newNumerator, newDenominator);
        }

        public Fraction multiply(Fraction other) {
            BigInteger newNumerator = numerator.multiply(other.numerator);
            BigInteger newDenominator = denominator.multiply(other.denominator);
            return new Fraction(newNumerator, newDenominator);
        }

        public Fraction divide(Fraction other) {
            BigInteger newNumerator = numerator.multiply(other.denominator);
            BigInteger newDenominator = denominator.multiply(other.numerator);
            return new Fraction(newNumerator, newDenominator);
        }

        public Fraction simplify() {
            BigInteger gcd = numerator.gcd(denominator);
            numerator = numerator.divide(gcd);
            denominator = denominator.divide(gcd);
            // 如果分母为负数，则调整符号使分母为正
            if (denominator.compareTo(BigInteger.ZERO) < 0) {
                numerator = numerator.negate();
                denominator = denominator.negate();
            }
            return this;
        }

        @Override
        public String toString() {
            if (denominator.equals(BigInteger.ONE)) {
                return numerator.toString();
            } else {
                return numerator + "/" + denominator;
            }
        }
    }

    public static void main(String[] args) {
        test056 rd = new test056();
        System.out.println(rd.calculate("1+5*7/8"));

    }
}

